package gat.common.util;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.AnonymousCOSCredentials;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.region.Region;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import java.util.UUID;

@Component
public class TencentCosUtil {

    @Resource
    private CosConfig config;

    private volatile COSClient putClient;
    private volatile COSClient readClient;

    public String uploadFile(MultipartFile multipartFile) {
        String objectName = getRandomImageName(Objects.requireNonNull(multipartFile.getOriginalFilename()), config.getFolder());
        File file = transferToFile(multipartFile);
        // 指定文件将要存放的存储桶
        String bucketName = config.getBucketName();
        // 指定文件上传到 COS 上的路径，即对象键。例如对象键为 folder/picture.jpg，则表示将文件 picture.jpg 上传到 folder 路径下
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, file);
        getPutClient().putObject(putObjectRequest);
        return config.getUrl() + objectName;
    }

    public String uploadInputStream(InputStream is, String key) {
        // 指定文件将要存放的存储桶
        String bucketName = config.getBucketName();
        // 指定文件上传到 COS 上的路径，即对象键。例如对象键为 folder/picture.jpg，则表示将文件 picture.jpg 上传到 folder 路径下
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, is, null);
        getPutClient().putObject(putObjectRequest);
        return config.getUrl() + key;
    }

    public String getUrl(String key) {
        return getReadClient().getObjectUrl(config.getBucketName(), key).toString();
    }

    public COSClient getPutClient() {
        if (putClient == null) {
            synchronized (TencentCosUtil.class) {
                if (putClient == null) {
                    putClient = createPutClient();
                }
            }
        }
        return putClient;
    }

    public COSClient getReadClient() {
        if (readClient == null) {
            synchronized (TencentCosUtil.class) {
                if (readClient == null) {
                    readClient = createGetClient();
                }
            }
        }
        return readClient;
    }

    private COSClient createPutClient() {
        COSCredentials cred =
            new BasicCOSCredentials(config.getSecretId(), config.getSecretKey());
        return createClient(cred);
    }

    private COSClient createGetClient() {
        COSCredentials cred = new AnonymousCOSCredentials();
        return createClient(cred);
    }

    private COSClient createClient(COSCredentials cosCredentials) {
        Region region = new Region(config.getRegion());
        ClientConfig clientConfig = new ClientConfig(region);
        clientConfig.setHttpProtocol(HttpProtocol.https);
        return new COSClient(cosCredentials, clientConfig);
    }

    private static File transferToFile(MultipartFile multipartFile) {
        // 选择用缓冲区来实现这个转换即使用java 创建的临时文件 使用 MultipartFile.transferto()方法 。
        File file = null;
        try {
            // 获取文件名
            String originalFilename = multipartFile.getOriginalFilename();
            // 获取最后一个"."的位置
            int cutPoint = originalFilename.lastIndexOf(".");
            // 获取文件名
            String prefix = originalFilename.substring(0, cutPoint);
            // 获取后缀名
            String suffix = originalFilename.substring(cutPoint + 1);
            // 创建临时文件
            file = File.createTempFile(prefix.length() < 3 ? UUID.randomUUID().toString().replace("-", "") : prefix,
                suffix);
            multipartFile.transferTo(file);
            // 删除临时文件
            file.deleteOnExit();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return file;
    }

    /**
     * 获取一个随机的文件名
     *
     * @param oranName 初始的文件名
     * @return 返回加uuid后的文件名
     */
    private static String getRandomImageName(String oranName, String folder) {
        // 获取一个uuid 去掉-
        String uuid = UUID.randomUUID().toString().replace("-", "");
        // 查一下是否带路径
        int cutPoint = oranName.lastIndexOf("/") + 1;
        // 如果存在路径
        if (cutPoint != 0) {
            // 掐头 如果开头是/ 则去掉
            String head =
                oranName.indexOf("/") == 0 ? oranName.substring(1, cutPoint) : oranName.substring(0, cutPoint);
            // 去尾
            String tail = oranName.substring(cutPoint);
            // 返回正确的带路径的图片名称
            return folder + head + uuid + tail;
        }
        String suffix = oranName.substring(oranName.lastIndexOf("."));
        // 不存在 直接返回
        if (folder.startsWith("/")) {
            return folder + uuid + suffix;
        } else {
            return "/" + folder + uuid + suffix;
        }
    }

}
